package cn.schoolwow.quickdao.module.database.parent.flow.executor.common;

import cn.schoolwow.quickdao.module.database.dml.common.domain.GetBatchParametersSupplier;
import cn.schoolwow.quickdao.module.database.dql.parent.domain.QueryContext;
import cn.schoolwow.quickdao.module.database.dql.subCondition.domain.SubQueryOption;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

public class BeforeExecuteFlow implements BusinessFlow {
    private Logger logger = LoggerFactory.getLogger(BeforeExecuteFlow.class);

    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        checkParameterCount(flowContext);
        setFormatSQL(flowContext);
    }

    @Override
    public String name() {
        return "执行SQL语句之前";
    }

    private void checkParameterCount(FlowContext flowContext){
        GetBatchParametersSupplier getBatchParametersSupplier = (GetBatchParametersSupplier) flowContext.getData("getBatchParametersSupplier");
        if(null!=getBatchParametersSupplier){
            //批处理更新语句此时不检查参数个数
            return;
        }

        String name = (String) flowContext.checkData("name");
        String sql = (String) flowContext.checkData("sql");
        List<Object> parameters = (List) flowContext.getData("parameters");

        //检查参数列表个数是否匹配
        int expectParameterCount = 0;
        for(int i=0;i<sql.length();i++){
            if(sql.charAt(i)=='?'){
                expectParameterCount++;
            }
        }
        long actualParameterCount = null==parameters?0:parameters.size();
        if(expectParameterCount>0&&actualParameterCount!=expectParameterCount){
            logger.warn("SQL语句参数个数不匹配\r\n名称:{}\r\n原始SQL:{}\r\n参数列表:{}", name, sql, parameters);
            QueryContext queryContext = (QueryContext) flowContext.getData("queryContext");
            if (null != queryContext) {
                logger.warn("Condition查询参数列表\r\nselect:{}\r\nfrom:{}\r\njoin:{}\r\nwhere:{}\r\nhaving:{}\r\nset:{}\r\n",
                        queryContext.selectParameters,
                        queryContext.fromParameters,
                        queryContext.joinParameters,
                        queryContext.whereParameters,
                        queryContext.havingParameters,
                        queryContext.setParameters
                );
                if (!queryContext.queryOption.subQueryOptionList.isEmpty()) {
                    StringBuilder builder = new StringBuilder("连表查询参数\n\n");
                    for(SubQueryOption subQueryOption:queryContext.queryOption.subQueryOptionList){
                        builder.append("表名:"+subQueryOption.subQueryTableOption.entity.tableName+"\r\n");
                        builder.append("别名:"+subQueryOption.subQueryTableOption.tableAliasName+"\r\n");
                        builder.append("where参数:"+subQueryOption.subQueryFragmentOption.whereParameterList+"\r\n");
                        builder.append("having参数:"+subQueryOption.subQueryFragmentOption.havingParameterList+"\r\n");
                    }
                    logger.warn(builder.toString());
                }
            }
            throw new IllegalArgumentException("SQL语句参数个数不匹配!预期个数:"+expectParameterCount+",实际个数:"+actualParameterCount);
        }
    }

    private void setFormatSQL(FlowContext flowContext){
        String sql = (String) flowContext.checkData("sql");
        List<Object> parameters = (List) flowContext.getData("parameters");

        //由于一个方法可能在内部调用多次executeQuery或者executeUpdate,执行sql前检查参数是否需要清空
        if(!sql.contains("?")&&null!=parameters&&!parameters.isEmpty()){
            parameters.clear();
        }

        flowContext.startFlow(new SetFormatStatementFlow())
                .putCurrentCompositeFlowData("parameters", parameters)
                .execute();
    }
}
